package com.roadmap.repo.db;

import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.type.NullableType;

import com.roadmap.common.RdcLogger;
import com.roadmap.exception.ServerException;

/** this class is for native SQL query */
public class RdcQuery {
	private final static Logger _log = RdcLogger.getLogger(RdcQuery.class);
	private Session _session;
	private SQLQuery _query;

	private RdcQuery(Session session, String sql) throws ServerException {
		_session = session;
		try {
			_query = _session.createSQLQuery(sql);
		}
		catch (HibernateException e) {
			_log.error(2);
			closeSession();
		}
	}

	public static RdcQuery getInstance(Session session, String sql)
			throws ServerException {
		return new RdcQuery(session, sql);
	}

	public void finalize() {
		closeSession();
	}

	private void closeSession() {
		if (_session != null && _session.isOpen()) {
			_session.close();
		}
	}

	public void addEntity(String alias, Class clazz) {
		_query = _query.addEntity(alias, clazz);
	}

	public void addScalar(String scalar) {
		addScalar(scalar, null);
	}

	public void addScalar(String scalar, NullableType type) {
		_query = (type != null) ? _query.addScalar(scalar, type) : _query
				.addScalar(scalar);
	}

	public void setParameters(Object[] params) {
		if (params != null) {
			for (int i = 0; i < params.length; i++) {
				_query.setParameter(i, params[i]);
			}
		}
	}

	public void setParameter(String alias, Object param) {
		if (alias != null && param != null) {
			_query.setParameter(alias, param);
		}
	}

	public void setParameterList(String name, List values) {
		if (name != null && values != null && values.size() > 0) {
			_query.setParameterList(name, values);
		}
	}

	public void setParameterList(String name, Object[] values) {
		if (name != null && values != null && values.length > 0) {
			_query.setParameterList(name, values);
		}
	}

	public void setMaxResults(int max) {
		_query.setMaxResults(max);
	}

	public List getResults() throws HibernateException {
		try {
			List results = _query.list();
			if(_log.isDebugEnabled()) {
				_log.debug("returned results number: " + results.size());
			}
			return results;
		}
		catch (HibernateException e) {
			_log.error("failed to execute query: " + _query.getQueryString(), e);
			throw e;
		}
		finally {
			closeSession();
		}
	}
	
	public Object getUniqueResult() throws HibernateException {
		try {
			return _query.uniqueResult();
		}
		catch (HibernateException e) {
			_log.error("failed to execute query: " + _query.getQueryString(), e);
			throw e;
		}
		finally {
			closeSession();
		}
	}
}
